package m3f.retrieval;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;

import org.jblas.DoubleMatrix;

public class CombineImages{
	
	public static enum Operator{avg, max, sum};
	
	private RandomReader rr = null;

	public CombineImages(String imageListFileName, String imageFeaturesFileName, String combinedImagesFile, String combinedImageFeaturesFileName, Operator op) throws IOException {
		
		System.out.println("loading image names...");
		Dictionary<String, Integer> imagesNames = loadNames(imageListFileName);
		
		rr = new RandomReader(imageFeaturesFileName);
		System.out.println("loading combined images file...");
		ArrayList<String[]> combinedImagesByCase = Rank.loadCombinedNames(combinedImagesFile);
		List<String> caseNames = new ArrayList<String>();
		List<int[]> combinedImagesByCaseIndices = new ArrayList<int[]>();	
		
		int step = 1;
		int combinedSize = combinedImagesByCase.size();
		if (combinedSize > 100){
			step = combinedSize / 100;
		}
		
		System.out.println("indexing combined images file...");
		for (int i = 0; i < combinedImagesByCase.size(); i++) {
			int[] indexes = new int[combinedImagesByCase.get(i).length - 1];
			for (int j = 0; j < combinedImagesByCase.get(i).length - 1; j++) {
				indexes[j] = imagesNames.get(combinedImagesByCase.get(i)[j + 1]);
			}
			caseNames.add(combinedImagesByCase.get(i)[0]);
			combinedImagesByCaseIndices.add(indexes);
			if (i % step == 0){
				System.out.println((i * 100) / combinedSize  + " %");
			}
		}
		
		//DoubleMatrix combinedImages = DoubleMatrix.zeros(combinedImagesByCaseIndexes.size(), rr.features);
		//combine image features
		int index = 0;
				
		BufferedWriter writer = new BufferedWriter(new FileWriter(combinedImageFeaturesFileName));
		
		System.out.println("generating combined images features file...");
	    for (int[] caseIndexes :combinedImagesByCaseIndices) {
	    	//combinedImages.putRow(index, combineFeatures(caseIndexes, op));
	    	DoubleMatrix combinedFeatures = combineFeatures(caseIndexes, op);
	    	for (int i = 0; i < rr.features; i++) {
	    		if (i != 0){
	    			writer.write(" ");
	    		}
    			writer.write(combinedFeatures.get(1,i - 1) + " ");
	    		
	    	}
	    	writer.write("\n");
	    	index++;
			if (index % step == 0){
				System.out.println((index * 100) / combinedSize  + " %");
			}
	    }
	    writer.close();
	}

	public DoubleMatrix combineFeatures(int[] indices, Operator op) {
		DoubleMatrix vector = DoubleMatrix.zeros(1, rr.features);
		for (int index : indices) {
			switch (op) {
			case sum:
				vector = vector.add(rr.getVector(index));
				break;
			case max:
				vector = vector.max(rr.getVector(index));
				break;
			default:
				vector = vector.add(rr.getVector(index));
				break;
			}			
		}
		return vector;
	}
	
	public static Dictionary<String, Integer> loadNames(String file){
		
		try{
			BufferedReader reader = new BufferedReader(new FileReader(file));
			Dictionary<String, Integer> names = new Hashtable<String, Integer>();
			String name;
			int index = 0;
			while((name = reader.readLine()) != null){
				names.put(name, index);
				index++;;
			}
			reader.close();
			return names;
		}catch(IOException ioe){
			ioe.printStackTrace();
		}
		return null;
	}
	
}
